package com.hrc.rpc.postProcessor;


import com.hrc.rpc.Filter.FilterConfig;
import com.hrc.rpc.annotation.RpcService;
import com.hrc.rpc.common.ServiceMeta;
import com.hrc.rpc.config.RpcProperties;
import com.hrc.rpc.netty.NettyServer;
import com.hrc.rpc.registry.RegistryFactory;
import com.hrc.rpc.registry.RegistryService;
import com.hrc.rpc.router.LoadBalancerFactory;
import com.hrc.rpc.serialization.SerializationFactory;
import com.hrc.rpc.utils.PropertiesUtils;
import com.hrc.rpc.utils.RpcServiceNameBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.lang.NonNull;

import java.util.HashMap;
import java.util.Map;

public class RpcProviderPostProcessor implements BeanPostProcessor, EnvironmentAware, InitializingBean {
    public static final Logger logger = LoggerFactory.getLogger(RpcProviderPostProcessor.class);
    RpcProperties rpcProperties;

    // 此处在linux环境下改为0.0.0.0
    private static final String serverAddress = "127.0.0.1";

    private final Map<String, Object> rpcServiceMap = new HashMap<>();

    @Override
    public void afterPropertiesSet() {

        Thread t = new Thread(() -> {
            try {
                new NettyServer().run();
            } catch (Exception e) {
                logger.error("start rpc server error.", e);
            }
        });
        t.setDaemon(true);
        t.start();
        SerializationFactory.init();
        RegistryFactory.init();
        LoadBalancerFactory.init();
        FilterConfig.initServiceFilter();
    }


    /**
     * 服务注册
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean,@NonNull String beanName) throws BeansException {
        Class<?> beanClass = bean.getClass();
        // 找到bean上带有 RpcService 注解的类
        RpcService rpcService = beanClass.getAnnotation(RpcService.class);
        if (rpcService != null) {
            // 可能会有多个接口,默认选择第一个接口
            String serviceName = beanClass.getInterfaces()[0].getName();
            if (!rpcService.serviceInterface().equals(void.class)){
                serviceName = rpcService.serviceInterface().getName();
            }
            String serviceVersion = rpcService.serviceVersion();
            try {
                // 服务注册
                int servicePort = rpcProperties.getPort();
                // 获取注册中心 ioc
                RegistryService registryService = RegistryFactory.get(rpcProperties.getRegisterType());
                ServiceMeta serviceMeta = new ServiceMeta();
                // 服务提供方地址
                serviceMeta.setServiceAddr(serverAddress);
                serviceMeta.setServicePort(servicePort);
                serviceMeta.setServiceVersion(serviceVersion);
                serviceMeta.setServiceName(serviceName);
                registryService.register(serviceMeta);
                // 缓存
                rpcServiceMap.put(RpcServiceNameBuilder.buildServiceKey(serviceMeta.getServiceName(),serviceMeta.getServiceVersion()), bean);
                logger.info("register server {} version {}",serviceName,serviceVersion);
            } catch (Exception e) {
                logger.error("failed to register service {}",  serviceVersion, e);
            }
        }
        return bean;
    }

    @Override
    public void setEnvironment(@NonNull Environment environment) {
        RpcProperties properties = RpcProperties.getInstance();
        PropertiesUtils.init(properties,environment);
        rpcProperties = properties;
        logger.info("读取配置文件成功");
    }
}
